// Copyright 2010 Google Inc. All Rights Reseved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.testing.testify.risk.frontend.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.testing.testify.risk.frontend.model.Project;
import com.google.testing.testify.risk.frontend.shared.rpc.DataRpc;
import com.google.testing.testify.risk.frontend.shared.rpc.DataRpcAsync;
import com.google.testing.testify.risk.frontend.shared.rpc.ProjectRpc;
import com.google.testing.testify.risk.frontend.shared.rpc.ProjectRpcAsync;
import com.google.testing.testify.risk.frontend.shared.rpc.UserRpc;
import com.google.testing.testify.risk.frontend.shared.rpc.UserRpcAsync;
/**
* Entry point for Test Analytics application.
*
* @author jimr@google.com (Jim Reardon)
*/
public class TaEntryPoint implements EntryPoint {
private Panel contentPanel;
private ProjectRpcAsync projectService;
private UserRpcAsync userService;
private DataRpcAsync dataService;
private static final String HOMEPAGE_HISTORY_TOKEN = "/homepage";
// URL related error messages.
private static final String INVALID_URL = "Invalid URL";
private static final String INVALID_URL_TEXT = "The page could not be found.";
private static final String INVALID_PROJECT_ID_TEXT = "No project with that ID was found.";
// Project-load related error messages.
private static final String ERROR_LOADING_PROJECT = "Error loading project";
private static final String ERROR_LOADING_PROJECT_TEXT =
"There was an error loading the requested project";
private static final String PROJECT_NOT_FOUND = "Project not found";
private static final String PROJECT_ID_NOT_FOUND_TEXT = "No project with that ID was found.";
/** UI for the currently opened project. */
private TaApplication currentApplicationInstance = null;
/**
* Entry point for the application.
*/
@Override
public void onModuleLoad() {
projectService = GWT.create(ProjectRpc.class);
userService = GWT.create(UserRpc.class);
dataService = GWT.create(DataRpc.class);
contentPanel = new LayoutPanel();
RootLayoutPanel.get().add(contentPanel);
// Handle history changes. (Such as clicking a navigation hyperlink.)
History.addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
handleUrl(historyToken);
}
});
handleUrl(History.getToken());
}
/**
* Handles the URL, updating any UI elements for the current Testify application if necessary.
*/
private void handleUrl(String url) {
// Intercept well-known pages.
if ((url.length() == 0) || ("/".equals(url)) || (HOMEPAGE_HISTORY_TOKEN.equals(url))) {
displayHomePage();
return;
}
// Expected format: "/project-id/target-page"
// or: "/project-id/target-page/page-data" (project data is passed into the project page).
// Thus part 0 will be an empty string, part 1 will be the project ID, part 2 the page name,
// and part 3 the page data.
String[] parts = url.split("/");
if ((parts.length < 2) || (parts[0].length() != 0)) {
displayErrorPage(INVALID_URL, INVALID_URL_TEXT);
return;
}
// The first part, the project ID.
Long projectId = tryParseLong(parts[1]);
if (projectId == null) {
displayErrorPage(INVALID_URL, INVALID_PROJECT_ID_TEXT);
return;
}
// Page name.
String pageName = (parts.length > 2 ? parts[2] : null);
// Page has data that should be sent to the target page.
String pageData = (parts.length > 3 ? parts[3] : null);
// Attempt to switch the page view.
if (currentApplicationInstance != null &&
(currentApplicationInstance.getProject().getProjectId().equals(projectId))) {
currentApplicationInstance.switchToPage(pageName, pageData);
} else {
// Otherwise, attempt to load the project and switch the view.
loadProjectAndSwitchToUrl(projectId, url);
}
}
/**
* Performs an asynchronous load of a project with the given ID name. Afterwards, navigates to the
* target URL.
*/
private void loadProjectAndSwitchToUrl(final long projectId, final String targetUrl) {
projectService.getProjectById(projectId,
new AsyncCallback<Project>() {
@Override
public void onFailure(Throwable caught) {
displayErrorPage(ERROR_LOADING_PROJECT, ERROR_LOADING_PROJECT_TEXT);
}
@Override
public void onSuccess(Project result) {
if (result == null) {
displayErrorPage(PROJECT_NOT_FOUND, PROJECT_ID_NOT_FOUND_TEXT);
} else {
displayProjectView(result);
handleUrl(targetUrl);
}
}
});
}
/**
* Switches the application's view to displays an error message.
*/
private void displayErrorPage(String errorType, String errorMessage) {
GWT.log("General error: " + errorType);
GeneralErrorPage errorPage = new GeneralErrorPage();
errorPage.setErrorType(errorType);
errorPage.setErrorText(errorMessage);
setPageContent(errorPage);
}
/**
* Switches the application's view to the home page.
*/
private void displayHomePage() {
final HomePage homePage = new HomePage(projectService, userService);
setPageContent(homePage);
}
/**
* Switches the application's view to a specific Project.
*/
public void displayProjectView(Project project) {
// All projects must be serialized (have a Project ID) first.
if (project.getProjectId() == null) {
return;
}
GWT.log("Switching to view project " + project.getProjectId().toString());
currentApplicationInstance = new TaApplication(project, projectService, userService,
dataService);
setPageContent(currentApplicationInstance);
}
/**
* Sets the GWT page to display the provided content.
*/
private void setPageContent(Widget content) {
contentPanel.clear();
contentPanel.add(content);
}
/**
* Attempts to parse the given string as integer, if not returns null.
*/
private Long tryParseLong(String text) {
Long result = null;
try {
return Long.parseLong(text);
} catch (NumberFormatException nfe) {
return null;
}
}
}